﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;

namespace MyPersonalAccountBook
{
    class TabControlHelper
    {
        private TabControl tabControl;

        private int targetTabIndex = -1;
        private TabAlignment targetAlignment = (TabAlignment)(-1);

        private Rectangle rc = Rectangle.Empty;

        private Pen pen = new Pen(Color.Black, 5);

        public TabControlHelper(TabControl tabControl)
        {
            this.tabControl = tabControl;
            tabControl.AllowDrop = true;

            tabControl.MouseMove += new MouseEventHandler(tabControl_MouseMove);
            tabControl.DragOver += new DragEventHandler(tabControl_DragOver);
            tabControl.DragLeave += new EventHandler(tabControl_DragLeave);
            tabControl.DragDrop += new DragEventHandler(tabControl_DragDrop);
        }

        void tabControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                tabControl.DoDragDrop(tabControl.SelectedTab, DragDropEffects.Move);
            }
        }

        void tabControl_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetData(typeof(TabPage)) == null)
            {
                e.Effect = DragDropEffects.None;
                return;
            }
            else
            {
                e.Effect = DragDropEffects.Move;
            }

            int idx = countTabTargetIndex(sender, e);
            TabAlignment alm = countTargetAlignment(sender, e);

            if (targetTabIndex != idx || targetAlignment != alm)
            {
                targetAlignment = alm;
                targetTabIndex = idx;
                updateRectangle();
            }
        }

        private void updateRectangle()
        {
            if (rc != Rectangle.Empty)
            {
                ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Thick);
            }

            if (targetTabIndex != -1)
            {
                rc = new Rectangle(tabControl.ItemSize.Width * targetTabIndex + 2, 0 + 3, 1, tabControl.ItemSize.Height);
                rc = tabControl.RectangleToScreen(rc);
            }
            else if (targetAlignment != (TabAlignment)(-1))
            {
                rc = tabControl.DisplayRectangle;
                if (targetAlignment == TabAlignment.Left)
                {
                    rc.Width = rc.Width / 2;
                }
                else if (targetAlignment == TabAlignment.Right)
                {
                    rc.X += rc.Width / 2;
                    rc.Width = rc.Width / 2;
                }
                else if (targetAlignment == TabAlignment.Top)
                {
                    rc.Height = rc.Height / 2;
                }
                else if (targetAlignment == TabAlignment.Bottom)
                {
                    rc.Y += rc.Height / 2;
                    rc.Height = rc.Height / 2;
                }
                rc = tabControl.RectangleToScreen(rc);
            }
            else
            {
                rc = Rectangle.Empty;
            }

            if (rc != Rectangle.Empty)
            {
                ControlPaint.DrawReversibleFrame(rc, Color.Black, FrameStyle.Thick);
            }
        }

        void tabControl_DragLeave(object sender, EventArgs e)
        {
            targetTabIndex = -1;
            targetAlignment = (TabAlignment)(-1);
            updateRectangle();
        }

        void tabControl_DragDrop(object sender, DragEventArgs e)
        {
            if ((int)targetAlignment >= 0 || targetTabIndex >= 0)
            {
                if (targetAlignment == TabAlignment.Bottom)
                {
                    Control cc = tabControl.Parent;

                    SplitContainer sc = new SplitContainer();
                    sc.Orientation = Orientation.Horizontal;
                    sc.Dock = tabControl.Dock;

                    cc.Controls.Remove(tabControl);
                    cc.Controls.Add(sc);

                    tabControl.Dock = DockStyle.Fill;
                    sc.Panel2.Controls.Add(tabControl);
                }
            }

            tabControl_DragLeave(null, null);
        }

        int countTabTargetIndex(object sender, DragEventArgs e)
        {
            if (tabControl.DisplayRectangle.Contains(tabControl.PointToClient(new System.Drawing.Point(e.X, e.Y))))
            {
                return -1;
            }

            TabPage page = e.Data.GetData(typeof(TabPage)) as TabPage;

            if (!tabControl.TabPages.Contains(page))
            {
                return tabControl.TabPages.Count;
            }
            else
            {
                int idx = tabControl.PointToClient(new System.Drawing.Point(e.X, e.Y)).X / tabControl.ItemSize.Width;

                return idx == tabControl.TabPages.IndexOf(page) ? -1 : idx;
            }

            // TODO for better
        }

        TabAlignment countTargetAlignment(object sender, DragEventArgs e)
        {
            System.Drawing.Rectangle rr = tabControl.DisplayRectangle;
            System.Drawing.Point pp = tabControl.PointToClient(new System.Drawing.Point(e.X, e.Y));

            if(!rr.Contains(pp)){
                return (TabAlignment)(-1);
            }

            double l = (pp.X - rr.Left) / (double)rr.Width;
            double t = (pp.Y - rr.Top) / (double)rr.Height;
            double r = (rr.Right - pp.X) / (double)rr.Width;
            double b = (rr.Bottom - pp.Y) / (double)rr.Height;

            double tt = System.Math.Min(l, System.Math.Min(t, System.Math.Min(r, b)));

            return tt == l ? TabAlignment.Left : tt == t ? TabAlignment.Top : tt == r ? TabAlignment.Right : TabAlignment.Bottom;
        }
    }
}
